#pragma once
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdint>
#include <unistd.h>

using namespace std;

#define DEFAULT_BUFFER_SIZE 1024

class buffer {
public:
    buffer(size_t size = DEFAULT_BUFFER_SIZE) 
        :_reader_idx(0), _writer_idx(0), _buffer(size)
    {}

    char *begin() {
        return &_buffer[0];
    }

    // 获取当前的写入位置
    char *get_write_pos() {
        return &_buffer[_writer_idx];
    }

    // 获取当前的读取位置
    const char *get_read_pos() const {
        return &_buffer[_reader_idx];
    }

    // 获取缓冲区末尾空闲空间大小
    uint32_t get_endofbuffer_size() const {
        return _buffer.size() - _writer_idx;
    }

    // 获取缓冲区首部空闲空间大小
    uint32_t get_beginofbuffer_size() const {
        return _reader_idx;
    }

    // 获取可读空间大小
    uint32_t get_readable_size() const {
        return _writer_idx - _reader_idx;
    }

    // 将读指针向后移动
    void move_read_pos(uint32_t len) {
        if(len > get_readable_size()) {
            cerr << "Error: move_read_pos out of range" << endl;
            exit(-1);
        }
        _reader_idx += len;
    }

    // 将写指针向后移动
    void move_write_pos(uint32_t len) {
        if(len > get_endofbuffer_size()) {
            cerr << "Error: move_write_pos out of range" << endl;
            exit(-1);
        }
        _writer_idx += len;
    }

    // 确保可写空间足够
    void make_enouth_space(uint32_t len) {
        // 如果剩余空间够什么也不做
        if(len <= get_endofbuffer_size()) {
            return;
        }

        // 如果整体空闲空间足够，则挪动数据
        if(len <= get_endofbuffer_size() + get_beginofbuffer_size()) {
            uint32_t len = get_readable_size();
            copy(get_read_pos(), get_read_pos() + len, begin());
            // 调整读写指针
            _reader_idx = 0;
            _writer_idx = len;
        }
        else {
            // 扩容，不要挪动数据，直接从写之后扩容即可
            size_t need_size = len + _writer_idx;
            size_t new_size = get_new_size(need_size);
            _buffer.resize(new_size);
        }
    }

    // 写入数据
    void writer(const void *buf, size_t len) {
        make_enouth_space(len);
        const char *bf = reinterpret_cast<const char*>(buf);
        copy(bf, bf + len, get_write_pos());
        move_write_pos(len);
    }   

    void buffer_writer(const buffer &data) {
        writer(data.get_read_pos(), data.get_readable_size());
    }

    void string_writer(const string &s) {
        writer(s.c_str(), s.size());
    }

    // 读取数据
    void reader(void *buf, size_t len) {
        if(len > get_readable_size()) {
            cerr << "reader error" << endl;
            exit(-1);
        }
        char *bf = reinterpret_cast<char*>(buf);
        copy(get_read_pos(), get_read_pos() + len, bf);
        move_read_pos(len);
    }

    buffer buffer_reader(size_t len) {
        buffer data(len);
        reader(data.get_write_pos(), len);
        data.move_write_pos(len);
        return data;
    }

    string string_reader(size_t len) {
        string s;
        s.resize(len);
        reader(const_cast<char*>(s.c_str()), len);
        return s;
    }

    string find_line() {
        const char *line = find(get_read_pos(), const_cast<const char*>(get_write_pos()), '\n');
        if(line == get_write_pos()) {
            return "";
        }
        return string_reader(line - get_read_pos() + 1);
    }

    void clear() {
        _reader_idx = _writer_idx = 0;
    }

private:
    // 快速找出一个合适n，使得2^n满足大于等于new_size的最小值
    size_t get_new_size(size_t need_size) const {
        size_t new_size = 1;
        while(new_size < need_size) {
            new_size <<= 1;
        }
        return min(new_size, _buffer.max_size());
    }

private:
    vector<char> _buffer;
    // 注意这里的读写指针只是一个相对于这块空间起始位置的一个偏移量
    // 并不是真正的物理内存地址
    // 写入和获取数据时都需要物理地址
    uint32_t _reader_idx;
    uint32_t _writer_idx;
};